﻿/*
 * By David Barrett, Microsoft Ltd. 2012. Use at your own risk.  No warranties are given.
 * 
 * DISCLAIMER:
 * THIS CODE IS SAMPLE CODE. THESE SAMPLES ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
 * MICROSOFT FURTHER DISCLAIMS ALL IMPLIED WARRANTIES INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR OF FITNESS FOR
 * A PARTICULAR PURPOSE. THE ENTIRE RISK ARISING OUT OF THE USE OR PERFORMANCE OF THE SAMPLES REMAINS WITH YOU. IN NO EVENT SHALL
 * MICROSOFT OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
 * BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THE
 * SAMPLES, EVEN IF MICROSOFT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION
 * OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
 * */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SOAP_Test_Application
{
    public class ClassSyntaxHighlighter
    {
        private RichTextBox _richTextBox = null;
        private ClassSyntaxHighlightColours _syntaxColours;

        public ClassSyntaxHighlighter(RichTextBox RTextBox)
        {
            _richTextBox = RTextBox;
            _syntaxColours = new ClassSyntaxHighlightColours();
        }

        public string RTFColourTable
        {
            get { return _syntaxColours.ColourTable; }
        }

        private string AddColourTable(string RTF)
        {
            // We need to add the colour table for the syntax highlighting.  Replace any existing colour table.
            int iCTableStart = RTF.IndexOf("{\\colortbl;");

            if (iCTableStart != -1)
            {
                // Need to replace existing colour table
                int iCTableEnd = RTF.IndexOf('}', iCTableStart);
                RTF = RTF.Remove(iCTableStart, iCTableEnd - iCTableStart);
                RTF = RTF.Insert(iCTableStart, _syntaxColours.ColourTable);
            }
            else
            {
                // Adding new colour table
                int iRTFLoc = RTF.IndexOf("\\rtf");
                int iInsertLoc = RTF.IndexOf('{', iRTFLoc);
                if (iInsertLoc == -1) iInsertLoc = RTF.IndexOf('}', iRTFLoc) - 1;
                RTF = RTF.Insert(iInsertLoc, _syntaxColours.ColourTable);
            }
            return RTF;
        }

        public void SyntaxHighlight()
        {
            // Add XML syntax highlighting

            string sRTF = AddColourTable(_richTextBox.Rtf);
            bool bWithinTag = false;
            bool bWithinTagName = false;
            bool bWithinQuotes = false;
            bool bWithinComment = false;

            for (int i = 0; i < sRTF.Length; i++)
            {
                if (bWithinTagName)
                {
                    if (sRTF[i] == ' ')
                    {
                        // After tag name, anything else within the tag must be an attribute
                        sRTF = sRTF.Insert(i, _syntaxColours.RTFAttributeNameColour);
                        i += _syntaxColours.RTFAttributeNameColour.Length;
                        bWithinTagName = false;
                    }
                }
                else if (bWithinTag)
                {
                    if (sRTF[i] == '"')
                    {
                        if (bWithinQuotes)
                        {
                            sRTF = sRTF.Insert(i+1, _syntaxColours.RTFAttributeNameColour);
                            i += _syntaxColours.RTFAttributeNameColour.Length+1;
                            bWithinQuotes = false;
                        }
                        else
                        {
                            sRTF = sRTF.Insert(i, _syntaxColours.RTFAttributeValueColour);
                            i += _syntaxColours.RTFAttributeValueColour.Length;
                            bWithinQuotes = true;
                        }
                    }
                }

                if (sRTF[i] == '<')
                {
                    if (!bWithinComment)
                    {
                        // Opening tag
                        bWithinTag = true;

                        // Update tag colour
                        sRTF = sRTF.Insert(i, _syntaxColours.RTFTagColour);
                        i += _syntaxColours.RTFTagColour.Length;

                        //Check for comments tags 
                        if (sRTF[i + 1] == '!')
                        {
                            if ( (sRTF[i + 2] == '-') && (sRTF[i + 3] == '-') )
                            {
                                sRTF = sRTF.Insert(i + 4, _syntaxColours.RTFCommentColour);
                                i += ( 4 + _syntaxColours.RTFCommentColour.Length );
                                bWithinComment = true;
                            }
                            else
                            {
                                sRTF = sRTF.Insert(i + 1, _syntaxColours.RTFTagNameColour);
                                bWithinTagName = true;
                                i += _syntaxColours.RTFTagNameColour.Length + 1;
                            }
                        }
                        else
                        {
                            sRTF = sRTF.Insert(i + 1, _syntaxColours.RTFTagNameColour);
                            bWithinTagName = true;
                            i += _syntaxColours.RTFTagNameColour.Length + 1;
                        }
                    }
                }
                
                if (sRTF[i] == '>')
                {
                    if (bWithinComment)
                    {
                        if (sRTF[i - 1] == '-' && sRTF[i - 2] == '-')
                        {
                            sRTF = sRTF.Insert(i - 2, _syntaxColours.RTFTagColour);
                            i += _syntaxColours.RTFTagColour.Length + 1;
                            sRTF = sRTF.Insert(i, _syntaxColours.RTFDefaultColour);
                            i += _syntaxColours.RTFDefaultColour.Length;
                            bWithinComment = false;
                            bWithinTag = false;
                        }
                    }
                    if (bWithinTag)
                    {
                        if ((sRTF[i - 1] == '/') || (sRTF[i - 1] == '?'))
                        {
                            sRTF = sRTF.Insert(i-1, _syntaxColours.RTFTagColour);
                        }
                        else
                            sRTF = sRTF.Insert(i, _syntaxColours.RTFTagColour);
                        i += _syntaxColours.RTFTagColour.Length+1;
                        sRTF = sRTF.Insert(i, _syntaxColours.RTFDefaultColour);
                        i += _syntaxColours.RTFDefaultColour.Length-1;
                        bWithinTagName = false;
                        bWithinTag = false;
                    }
                }
            }
            _richTextBox.Rtf = sRTF;
        }
    }
}
